#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time    : 2025/4/15 上午9:59
@Author  : Suger
@File    : bridge.py
@Desc    : 
"""
import os
import json
import platform
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

from worker.clip_worker import ClipVideoQtThread
from worker.video_deduplication_worker import VideoDeduplicationQtThread
from worker.video_synthesis_worker import VideoSynthesisWorker
from worker.audio_and_video_separation_wowrker import AudioAndVideoSeparationWorker
from worker.merge_audio_worker import MergeAudioWorker
from worker.extract_audio_worker import ExtractAudioWorker
from worker.write_worker import WriteWorkerQtThread
from worker.login_worker import LoginWorkerQtThread
from worker.humanize_worker import HumanizeWorker
from worker.ident_audio import IdentAudioWorkerQtThread
from worker.ident_audio_context import IdentAudioContextWorkerQtThread
from worker.data_asve_srt_file import SaveSrtFileWorkerQtThread
from worker.rewrite_worker import RewriteWorkerQtThread
from worker.load_audio_materials import LoadAudioMaterialsWorker
from worker.synthesis_audio_worker import SynthesisAudioWorker
from worker.batch_synthesis_or_ident_worker import BatchSynthesisOrIdentWorker
from worker.load_source_materials_worker import LoadAudioVideoMaterialsWorker
from worker.ai_mix_worker import AiMixSynthesisWorker



from utils.load_file import *
from log import log

headers = {"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QxIiwidWlkIjoiOGU0NGJiNGY4OTkyOWFiMiIsImlkIjo0LCJ0eXBlIjoibWluaSIsImV4cCI6MTc0NTgyODk0M30.hnvUB2mgPbCAC29DwT4z9lSB6XqNe0Bogx0NQeYCkHM"}


class Bridge(QObject):
    started = pyqtSignal(str)
    finished = pyqtSignal(str)     # emit(result)
    failed = pyqtSignal(Exception)    # emit(exception)
    stopped = pyqtSignal(str)
    result = pyqtSignal(str)
    ident_result = pyqtSignal(str)
    ident_context_result = pyqtSignal(str)
    rewrite_result = pyqtSignal(str)
    source_result = pyqtSignal(str)



    batch_ident_and_synthesis_result = pyqtSignal(str)
    select_files_result = pyqtSignal(str, list, int)
    select_folder_result = pyqtSignal(str, str)
    select_folder_normal_shot_path_input = pyqtSignal(str, int, str, str, int)
    auto_mix_folder_result = pyqtSignal(str, str, int, float, float, float)
    choose_single_ident_audio_file_result = pyqtSignal(str, str, float)
    load_audio_model_result = pyqtSignal(str)



    def __init__(self):
        super().__init__()
        self.current_thread = None


    @pyqtSlot(str)
    def __init_user_info(self, data):
        """初始化headers"""
        # {
        #     "code": 1,
        #     "msg": "登录成功",
        #     "data": [
        #         {
        #             "username": "test1",
        #             "nickname": "武帝",
        #             "avatar": "",
        #             "phone": "",
        #             "amount": "788.00",
        #             "batches": "530.00",
        #             "uid": "8e44bb4f89929ab2",
        #             "level": "普通",
        #             "is_proxy": "是",
        #             "referrer_name": "proxy",
        #             "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QxIiwidWlkIjoiOGU0NGJiNGY4OTkyOWFiMiIsImlkIjo0LCJ0eXBlIjoibWluaSIsImV4cCI6MTc0NTU2OTI5NX0.ASHyw9Ete0zFqahDiEeWTsWoj5HWN4SsZMQy6_HnjQQ",
        #             "token_type": "bearer"
        #         }
        #     ]
        # }
        headers.update({
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {data["data"][0]["access_token"]}'
        })

    @pyqtSlot(str)
    def open_file(self, file_name):
        """打开文件/文件夹"""
        if platform.system() == 'Windows':
            os.startfile(file_name)
        elif platform.system() == 'Darwin':
            os.system('open ' + file_name)

    @pyqtSlot(str)
    def choose_single_ident_audio_file(self, eid):
        """单个音视频识别文件"""
        file_filter = "所有音视频文件 (*.mp4 *.mov *.avi *.mkv *.mp3 *.wav *.m4a *.acc);;MP4 文件 (*.mp4);;MOV 文件 (*.mov);;AVI 文件 (*.avi);;MKV 文件 (*.mkv);; MP3 文件 (*.mp3);; WAV 文件 (*.wav);; M4A 文件 (*.m4a);; ACC 文件 (*.acc)"
        file, _ = QFileDialog.getOpenFileName(None, "选择文件", "", file_filter)
        if file:
            self.choose_single_ident_audio_file_result.emit(eid, file, get_video_info(file)["duration"])


    @pyqtSlot(str)
    def choose_folder_and_read_video_and_audio_files(self, eid):
        """选择文件"""
        file = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if file:
            files = batch_scan_folder(file, suffixes=['.mp4', '.mov', '.avi', '.mkv', '.mp3', '.wav', '.flac'])
            self.select_files_result.emit(eid, files, len(files))
            self.select_folder_result.emit(eid, file)

    @pyqtSlot(str)
    def choose_video_and_audio_files(self, eid):
        """选择文件"""
        file_filter = "所有音视频文件 (*.mp4 *.mov *.avi *.mkv *.mp3 *.wav *.m4a *.acc);;MP4 文件 (*.mp4);;MOV 文件 (*.mov);;AVI 文件 (*.avi);;MKV 文件 (*.mkv);; MP3 文件 (*.mp3);; WAV 文件 (*.wav);; M4A 文件 (*.m4a);; ACC 文件 (*.acc)"
        file, _ = QFileDialog.getOpenFileName(None, "选择文件", "", file_filter)
        if file:
            self.select_files_result.emit(eid, [get_video_info(file)], 1)


    @pyqtSlot(str)
    def choose_folder_and_read_video_files(self, eid):
        """选择文件"""
        file = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if file:
            files = batch_scan_folder(file)
            self.select_files_result.emit(eid, files, len(files))
            self.select_folder_result.emit(eid, file)

    @pyqtSlot(str, str)
    def choose_file(self, eid, suffix='mp4'):
        """选择文件"""
        if suffix == 'mp4':
            file_filter = "所有视频文件 (*.mp4 *.mov *.avi *.mkv);;MP4 文件 (*.mp4);;MOV 文件 (*.mov);;AVI 文件 (*.avi);;MKV 文件 (*.mkv)"
        elif suffix == 'audio':
            file_filter = "所有音频文件 (*.mp3 *.wav *.flac);;MP3 文件 (*.mp3);;WAV 文件 (*.wav);;FLAC 文件 (*.flac)"
        elif suffix == 'image':
            file_filter = "所有图片文件 (*.png *.jpg *.jpeg *.bmp);;PNG 文件 (*.png);;JPEG 文件 (*.jpg *.jpeg);;BMP 文件 (*.bmp)"
        else:
            file_filter = "所有文件 (*.*)"
        file, _ = QFileDialog.getOpenFileName(None, "选择文件", "", file_filter)
        if file:
            self.select_folder_result.emit(eid, file)

    @pyqtSlot(str)
    def choose_folder(self, eid):
        """选择文件夹"""
        folder = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if folder:
            self.select_folder_result.emit(eid, folder)

    @pyqtSlot(str, int, str, str)
    def choose_folder_input(self, channel, index, name, suffix):
        """选择文件夹;读取文件夹视频文件数量"""
        folder = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if os.path.isdir(folder):
            if suffix == 'video':
                count = load_file_count(folder)
            elif suffix == 'audio':
                count = load_file_count(folder, suffixes=['.mp3', '.wav', '.flac'])
            else:
                raise Exception("不支持的格式")
            self.select_folder_normal_shot_path_input.emit(channel, index, folder, name, count)

    @pyqtSlot(str, int, str)
    def choose_file_input(self, channel, index, suffix='mp4'):
        """选择文件夹;读取文件夹视频文件数量"""
        file, _ = QFileDialog.getOpenFileName(None, "选择文件", "", f"选择视频文件 (*.{suffix})")
        if os.path.isfile(file):
            self.select_folder_normal_shot_path_input.emit(channel, index, file, file, 1)

    @pyqtSlot(str)
    def auto_mix_folder_input(self, eid):
        """自动混剪选择文件夹"""
        file = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if file:
            files = batch_scan_folder(file)
            duration_items = [file.get("duration") for file in files]
            mix_times = min(duration_items)
            max_times = max(duration_items)
            sum_times = sum(duration_items)
            self.auto_mix_folder_result.emit(eid, file, len(files), mix_times, max_times, sum_times)

    @pyqtSlot(str)
    def batch_ident_and_synthesis(self, suffix):
        """批量识别音频并合成"""
        file = QFileDialog.getExistingDirectory(None, "选择文件夹")
        if file:
            if suffix == 'audio/video':
                file_suffix = ['.mp4', '.mov', '.avi', '.mkv', '.mp3', '.wav', '.flac']
                files = batch_scan_folder(file, file_suffix)
            elif suffix == 'text':
                file_suffix = ['.txt']
                files = load_files(file, file_suffix)
                if files:
                    files = [{"file": file, "duration": 0, "size": os.path.getsize(file)} for file in files]
            else:
                raise Exception("不支持的格式")

            self.batch_ident_and_synthesis_result.emit(json.dumps(files))


    ###################  以下为后台任务  ##############


    def _stop_thread(self):
        if self.current_thread is not None and self.current_thread.isRunning():
            self.current_thread.terminate()
            self.current_thread.wait()
            self.current_thread = None

    @pyqtSlot()
    def stop(self):
        self._stop_thread()


    @pyqtSlot(str, str, str, str)
    def start_clip(self, channel, input_files, output_folder, arg):
        """视频剪辑"""
        log.debug(f"start_clip: {channel}, {input_files}, {output_folder}, {arg}")
        self._stop_thread()
        input_files = json.loads(input_files)
        self.current_thread = ClipVideoQtThread(channel, input_files, output_folder, arg)
        self.current_thread.started.connect(lambda: self.started.emit("开始分镜"))
        self.current_thread.finished.connect(lambda: self.finished.emit("分镜完成"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()

    @pyqtSlot(str)
    def video_deduplication(self, content):
        """视频去重"""
        self._stop_thread()
        self.current_thread = VideoDeduplicationQtThread(content)
        self.current_thread.started.connect(lambda: self.started.emit("开始去重"))
        self.current_thread.finished.connect(lambda: self.finished.emit("去重结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def video_systhesis(self, content):
        """视频合成"""
        log.debug(f"video_systhesis: {content}")
        self._stop_thread()
        self.current_thread = VideoSynthesisWorker(content)
        self.current_thread.started.connect(lambda: self.started.emit("开始合成"))
        self.current_thread.finished.connect(lambda: self.finished.emit("合成结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str, str)
    def audio_and_video_separation(self, input_file, output_folder):
        """音视频分离"""
        self._stop_thread()
        self.current_thread = AudioAndVideoSeparationWorker(input_file, output_folder)
        self.current_thread.started.connect(lambda: self.started.emit("开始音视频分离"))
        self.current_thread.finished.connect(lambda: self.finished.emit("音视频分离结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str, str, int)
    def extract_audio(self, files_path, output_folder, state):
        """提取音频"""
        self._stop_thread()
        self.current_thread = ExtractAudioWorker(files_path, output_folder, state)
        self.current_thread.started.connect(lambda: self.started.emit("开始提取音频"))
        self.current_thread.finished.connect(lambda: self.finished.emit("提取音频结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()



    @pyqtSlot(str, str)
    def merge_audio(self, files_path, output_folder):
        """合并音频"""
        self._stop_thread()
        self.current_thread = MergeAudioWorker(json.loads(files_path), output_folder)
        self.current_thread.started.connect(lambda: self.started.emit("开始合并音频"))
        self.current_thread.finished.connect(lambda: self.finished.emit("合并音频结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str, str, str)
    def general_write(self, channel, src, desc):
        """通用写作"""
        self._stop_thread()
        if not headers.get('Authorization'):
            print("请先登录")
            self.finished.emit("请先登录")
            return
        self.current_thread = WriteWorkerQtThread(channel, src, desc, headers)
        self.current_thread.finished.connect(lambda: self.finished.emit("写作结束"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.start()


    @pyqtSlot(str, str)
    def login(self, username, password):
        """登录"""
        self._stop_thread()
        self.current_thread = LoginWorkerQtThread(username, password)
        self.current_thread.result.connect(self.__init_user_info)
        self.current_thread.finished.connect(lambda: self.finished.emit("登录成功"))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def humanize(self, content):
        """通用写作"""
        self._stop_thread()
        if not headers.get('Authorization'):
            self.finished.emit("请先登录")
            print("请先登录")
            return
        self.current_thread = HumanizeWorker(content, headers)
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.start()


    @pyqtSlot(str)
    def batch_ident_audio(self, files):
        """批量音视频识别"""
        self._stop_thread()
        self.current_thread = IdentAudioWorkerQtThread(files, headers)
        self.current_thread.result.connect(lambda result: self.ident_result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def ident_audio_context(self, file):
        """批量音视频识别"""
        self._stop_thread()
        self.current_thread = IdentAudioContextWorkerQtThread(file, headers)
        self.current_thread.result.connect(lambda result: self.ident_context_result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def save_srt_file(self, content):
        """保存srt文件"""
        self.current_thread = SaveSrtFileWorkerQtThread(content)
        self.current_thread.finished.connect(lambda: self.finished.emit("保存srt文件成功"))
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def rewrite(self, content):
        """文案重写"""
        self._stop_thread()
        if not headers.get('Authorization'):
            self.finished.emit("请先登录")
            print("请先登录")
            return
        self.current_thread = RewriteWorkerQtThread(content, headers)
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.result.connect(lambda result: self.rewrite_result.emit(result))
        self.current_thread.start()


    @pyqtSlot()
    def load_audio_model(self):
        """加载音频模型"""
        self._stop_thread()
        if not headers.get('Authorization'):
            self.finished.emit("请先登录")
            print("请先登录")
            return
        self.current_thread = LoadAudioMaterialsWorker(headers)
        self.current_thread.result.connect(lambda result: self.load_audio_model_result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()

    @pyqtSlot(str)
    def synthesis_audio(self, content):
        print("开始合成音频")
        self._stop_thread()
        self.current_thread = SynthesisAudioWorker(content, headers)
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str)
    def batch_synthesis_or_ident(self, content):
        """批量合成或识别"""
        print("开始批量合成或识别")
        self._stop_thread()
        self.current_thread = BatchSynthesisOrIdentWorker(content, headers)
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()


    @pyqtSlot(str, int)
    def load_audio_video_materials(self, source, page):
        """加载音频视频素材"""
        self._stop_thread()
        if not headers.get('Authorization'):
            self.finished.emit("请先登录")
            print("请先登录")
            return
        self.current_thread = LoadAudioVideoMaterialsWorker(source, page, headers)
        self.current_thread.result.connect(lambda result: self.source_result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()

    @pyqtSlot(str, int, str, str, str)
    def AiMix_sybthesis(self, file_path, count, output_folder, subtitle, voice):
        """AI合成"""
        self._stop_thread()
        if not headers.get('Authorization'):
            self.finished.emit("请先登录")
            print("请先登录")
            return
        self.current_thread = AiMixSynthesisWorker(file_path, count, output_folder, subtitle, voice, headers)
        self.current_thread.result.connect(lambda result: self.result.emit(result))
        self.current_thread.failed.connect(lambda e: self.failed.emit(e))
        self.current_thread.start()